﻿using System;
using System.ServiceModel;

namespace TfsRollUp.Core
{
    /// <summary>
    /// Wcf endpoint listener for <see cref="IManager"/> implemented in ManagerClient
    /// <p/>Enables clients to access the <see cref="IManager" /> operations without restarting Tfs
    /// </summary>
    internal class Receiver : IDisposable
    {
        #region Constructors
        private Receiver() { }

        /// <summary>
        /// Connect
        /// </summary>
        /// <param name="service"></param>
        internal Receiver(Service service)
        {
            _service = service;
            _manager = new Manager(service);
        }

        #endregion

        #region Public Operations

        /// <summary>
        ///  If the service host can be started, true will be returned. If false is returned  another process owns the pipe.     
        /// </summary>
        /// <returns></returns>
        internal bool ServiceOn()
        {
            return (_operational = HostThisService());
        }

        /// <summary>
        /// Stop the service
        /// </summary>
        internal void ServiceOff()
        {
            if (_host != null)
                if (_host.State != CommunicationState.Closed)
                    _host.Close();
            _operational = false;
        }
        #endregion

        #region WCF Operations

        /// <summary>
        /// The thread which will listen for communications  from the other side of the pipe.    
        /// </summary>
        /// <returns>Operational flag</returns>
        private bool HostThisService()
        {
            try
            {
                _host = new ServiceHost(_manager, new Uri(Constants.URI));

                // Usage BasicHttpBinding can be used if this is         
                // not going to be on the local machine.         
                _host.AddServiceEndpoint(typeof(IManager), new NetNamedPipeBinding(), Constants.DefaultPipeName);
                _host.Open();
                _operational = true;
            }
            catch (Exception ex)
            {
                error = ex;
                _operational = false;
            }
            return _operational;
        }
        #endregion

        #region Public Properties

        /// <summary>
        /// Any error will be placed here
        /// </summary>
        internal Exception error = null;

        #endregion

        #region Private Variables

        private Manager _manager;
        private bool _operational = false;
        private ServiceHost _host = null;
        private bool _disposed = false;
        private Service _service;


        #endregion

        #region IDisposable
        /// <summary>
        /// Kill
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                ((IDisposable)_host).Dispose();
                _service.Dispose();

                // Set the sentinel.
                _disposed = true;

                // Suppress finalization of this disposed instance.
                if (disposing)
                {
                    GC.SuppressFinalize(this);
                }
            }
        }

        /// <summary>
        /// Prepare kill
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
        }

        /// <summary>
        /// PrePreKill
        /// </summary>
        ~Receiver()
        {
            Dispose(false);
        }
        #endregion
    }
}